package gogoqiu.java.base;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;

public class FileUtils {
    public static void copyStream2Stream(InputStream is, FileOutputStream fileOutputStream ){
        try {
            byte[] buf = new byte[ 1024 ];
            long len;
            while( (len = is.read(buf) )!=-1 ) {
                fileOutputStream.write( buf, 0, (int)len );
            }
            fileOutputStream.close();
        }catch (IOException ioException ){
            ioException.printStackTrace();
        }
    }

    public static long checkSize( File file ){
        return file.length();
    }

    /**
     * 检测文件是否为UTF-8编码
     * @param filePath 文件路径
     * @return 如果可能是UTF-8编码返回true，否则返回false
     * @throws IOException 读取文件时发生错误
     */
    public static boolean isUtf8Encoded(String filePath) throws IOException {
        try (FileInputStream fis = new FileInputStream(filePath);
             //Environment.DIRECTORY_DOCUMENTS;
             BufferedInputStream bis = new BufferedInputStream(fis)) {

            byte[] buffer = new byte[4096];
            int bytesRead;
            int index = 0;

            while ((bytesRead = bis.read(buffer)) != -1) {
                while (index < bytesRead) {
                    // 如果是ASCII字符(0-127)，直接跳过
                    if ((buffer[index] & 0x80) == 0) {
                        index++;
                        continue;
                    }

                    // 检查多字节序列
                    int bytesNeeded;
                    int mask;

                    // 检查第一个字节判断需要多少个后续字节
                    if ((buffer[index] & 0xE0) == 0xC0) { // 2字节序列: 110xxxxx
                        bytesNeeded = 1;
                        mask = 0x1F;
                    } else if ((buffer[index] & 0xF0) == 0xE0) { // 3字节序列: 1110xxxx
                        bytesNeeded = 2;
                        mask = 0x0F;
                    } else if ((buffer[index] & 0xF8) == 0xF0) { // 4字节序列: 11110xxx
                        bytesNeeded = 3;
                        mask = 0x07;
                    } else {
                        // 不符合UTF-8格式
                        return false;
                    }

                    // 检查是否有足够的后续字节
                    if (index + bytesNeeded >= bytesRead) {
                        // 缓冲区末尾，需要更多数据，跳出循环继续读取
                        break;
                    }

                    // 检查后续字节是否符合10xxxxxx格式
                    for (int i = 1; i <= bytesNeeded; i++) {
                        if ((buffer[index + i] & 0xC0) != 0x80) {
                            return false;
                        }
                    }

                    // 检查第一个字节的有效位是否为0（排除过度编码的情况）
                    if ((buffer[index] & mask) == 0) {
                        return false;
                    }

                    index += bytesNeeded + 1;
                }
            }
            return true;
        }
    }

    // 文件读取出字符串, 会保留文件头吗
    public static String readUtf8File( String filePath ) throws IOException {
        StringBuilder content = new StringBuilder();
        // 使用try-with-resources自动关闭资源
        try (FileInputStream fis = new FileInputStream(filePath);
             InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8);
             BufferedReader br = new BufferedReader(isr)) {

            String line;
            // 逐行读取
            while ((line = br.readLine()) != null) {
                content.append(line).append(System.lineSeparator());
            }
        }
        return content.toString();
    }

    /**
     * 将字符串以UTF-8编码写入文件
     * @param str 要保存的字符串
     * @param filePath 目标文件路径
     * @return 保存成功返回true，否则返回false
     */
    public static boolean saveStringToFile(String str, String filePath) throws IOException {
        // 空字符串判断
        if (str == null) {
            return false;
        }

        OutputStreamWriter osw = null;

        // 创建文件输出流，指定文件路径
        FileOutputStream fos = new FileOutputStream(filePath);

        // 包装为OutputStreamWriter并指定UTF-8编码
        osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);

        // 写入字符串
        osw.write(str);
        osw.flush();
        osw.close();
        return true;
    }

    // 方法2：使用Java 8的Files.readAllBytes（更简洁）
    public static String readFileWithFiles(String filePath) throws IOException {
        // 读取所有字节并使用UTF-8编码转换为字符串
        byte[] bytes = new byte[0];
        
        bytes = Files.readAllBytes(Paths.get(filePath));
        return new String(bytes, StandardCharsets.UTF_8);
    }
}
